package qa.tests;

import java.lang.reflect.Method;

import org.aspectj.lang.Signature;
import org.junit.Test;

public aspect AssertAspect {

    private int numberOfTimesAssertCalled = 0;

    pointcut inTest() : execution(@org.junit.Test void *.*(..));

    pointcut assertCalled() : call(static * org.junit.Assert.*(..));

    before(): assertCalled() {
        numberOfTimesAssertCalled++;
    }

    void around(): inTest() {
        Signature testMethodSignature = thisJoinPointStaticPart.getSignature();
        Class<?> clazz = testMethodSignature.getDeclaringType();
        Statistics statistics = statisticsForMethodUnderTest(clazz, testMethodSignature);
        reset();

        try {
            proceed();
        } catch (RuntimeException e) {
            statistics.exceptionThrown();
            throw e;
        } catch (AssertionError e) {
            throw e;
        } catch (Error e) {
            statistics.exceptionThrown();
            throw e;
        } finally {
            statistics.increment(numberOfTimesAssertCalled);
            StatisticsWriter.instance().write(statistics);
        }
    }

    private Statistics statisticsForMethodUnderTest(Class<?> clazz, Signature testMethodSignature) {
        Statistics statistics = null;
        try {
            Method testMethod = clazz.getMethod(testMethodSignature.getName(), null);
            statistics = new Statistics(testMethod);
            determineIfExceptionIsExpected(testMethod, clazz, statistics);
        } catch (Exception ignore) {

        }
        return statistics;
    }

    private void reset() {
        numberOfTimesAssertCalled = 0;
    }

    private void determineIfExceptionIsExpected(Method testMethod, Class<?> clazz, Statistics statistics) {
        try {
            Test testAnnotation = testMethod.getAnnotation(Test.class);
            if (!Test.None.class.equals(testAnnotation.expected())) {
                statistics.increment();
            }
        } catch (Exception ignore) {
            ignore.printStackTrace();
        }
    }

}
